; Grange Murder verb code. Graham M Jones 7/6/89.
;
 begin
cif debugmode
code -
 prs "*****AAVERBS*****"
code +
cend
;
.CALLVERB
; GIVEN VERB,PREP,NOUN1,NOUN2,
; DO THE JUMP-TABLE INDEXING ON THE VERB
code -
 gosub CV1
code +
 return
;
code -
.CV1
 object=noun1
 if verb>maxECHO then TRANSverb
 if verb>minECHOminus1 then ECHOverb
 if verb>maxintransitive then TRANSverb
 jump intranstable verb
.EchoVerb
 return
;---
.TRANSverb
 IF NOUN1<>NULLOBJECT THEN CVGOTNOUN
;
.TVnoOBJECTerror
cif debugmode
 message cr
 prs " TVNOOBJECT "
 message cr
cend
 return
;
.CVGOTNOUN
 if verb>maxTRANSITIVE then noverb
 x1=verb
 jump transtable x1
.NOverb
cif debugmode
 message cr
 prs " NOVERB "
 print verb
 prs " ACTOR "
 print actor
 message cr
cend
 return
;---
.intranstable
.transtable
 data @noverb,@noverb,@noverb,@noverb ; 0-3
 data @noverb,@noverb,@noverb,@noverb ; 4-7
 data @noverb,@noverb,@noverb,@noverb ; 8-11
 data @noverb,@noverb,@noverb,@noverb ; 12-15
 data @noverb,@noverb,@noverb,@noverb ;16-19
 data @noverb,@noverb,@noverb,@noverb ; 20-23
 data @noverb,@noverb,@noverb,@noverb ; 24-27
 data @noverb,@noverb,@noverb,@noverb ; 28-31
 data @noverb,@ring ; (32=parsewait called elsewhere)
 data @noverb,@noverb ; 34-35
 data @noverb,@noverb,@noverb,@noverb ; 36-39
 data @noverb,@noverb,@noverb,@noverb ; 40-43
 data @noverb,@noverb,@noverb,@noverb ; 44-47
 data @sit,@noverb,@noverb,@noverb ; 48-51
 data @noverb,@noverb,@noverb,@noverb ; 52-55 
 data @noverb,@noverb,@noverb,@noverb ; 56-59 
 data @noverb,@noverb,@noverb,@noverb ; 60-63
 data @noverb,@noverb,@noverb,@noverb ; 64-67
 data @noverb,@noverb,@noverb ; 68-70
 data @noverb,@noverb,@noverb,@noverb,@noverb ; 71-75
 data @noverb,@noverb,@noverb,@noverb ; 76-79
 data @noverb,@noverb,@noverb,@noverb,@noverb,@noverb ; 80-85
 data @noverb,@noverb,@noverb,@noverb ; 86-89
 data @noverb,@noverb,@noverb ; 90-92
 data @noverb,@noverb ; 93-94
 data @noverb,@noverb,@noverb,@noverb,@noverb ; 95-99
;
 data @examine,@noverb,@noverb,@noverb ; 100-103
 data @noverb,@take,@noverb,@drop ; 104-107
 data @put,@noverb,@noverb,@noverb ; 108-111
 data @noverb,@noverb,@open,@close ; 112-115
 data @noverb,@noverb,@noverb,@noverb ; 116-119
 data @noverb,@noverb,@noverb,@noverb ; 120-123
 data @noverb,@answer,@dial,@noverb ; 124-127
; data @noverb,@noverb,@noverb,@noverb ; 128-131
; data @noverb,@noverb,@noverb,@noverb ; 132-135
; data @noverb,@noverb ; 136,@137
; data @noverb,@noverb ;; menugoto ; 138,@139 (gdfind)
; data @noverb,@noverb,@noverb,@noverb ; 140-143
; data @noverb,@noverb,@noverb,@noverb ; 144-147
; data @noverb,@noverb,@noverb,@noverb ; 148-151
; data @noverb,@noverb,@noverb,@noverb ; 152-155
; data @noverb,@noverb,@noverb,@noverb ; 156-159
; data @noverb,@noverb,@noverb,@noverb ; 160-163
; data @noverb,@noverb,@noverb,@noverb ; 164-167
; data @noverb,@noverb,@noverb,@noverb ; 168-171
; data @noverb,@noverb,@noverb,@noverb ; 172-175
; data @noverb,@noverb,@noverb,@noverb ; 176-179
;---
.take
code +
 POS=ACTOR
 HIPOS=CARRIED
 GOSUB @MOVEOBJECT
 GOSUB @PrintActorActionDot
 gosub @AASpecialTake
code -
 return
;---
.drop
; Does object look sensible on the ground?
 gosub CanObjectBeDropped
 if result=false then dropdead ; new command set up
code +
 gosub @AASpecialDrop ; prep is height to drop object at (used in 
; racetracks)
 prep=0
 POS=room
 HIPOS=0
 GOSUB @MOVEOBJECT
 GOSUB @PrintActorActionDot
code -
.dropdead
 return
;---
; Can object be dropped on the ground?
; If not, RESULT=FALSE & new command is set up to 
; put object in a container
.CanObjectBeDropped
 result=true
;
;=====
; Coats look silly when dropped
 if object<minclothes then @COBDRet
 if object>maxclothes then @COBDRet
 if object=pinnafore then @COBDRet
; Find a suitable container for the coat
 verb=iPUT
 noun2=noun1 ; noun2 is the CONTAINMENT-to-be
 prep=ipIN
 noun1=wardrobe ; wardrobe is first choice
 x1=currentpos(noun1)
 if x1=room then COBDNewCommand
 noun1=chest ; chest is second choice
 x1=currentpos(noun1)
 if x1=room then COBDNewCommand
; there is no suitable container in this room
 if actor<>user then COBDFalse
 message cr
 m1=2841 ; no suitable container
code +
 gosub @printm1dot
code -
 goto COBDFalse
;=====
;
.COBDNewCommand
code +
 gosub @intelligentpop ; pop the DROP command
 gosub @SinglePushFifo ; push the PUT command
 commandfinished=false
 executeprocessed=false
code -
.COBDFalse
 result=false
.COBDRet
 return
;---
.EXAMINE
code +
 noun2=nullobject ; to avoid confusing data.
 if actor=user then examine0
 gosub @printactoractiondot
 goto @examret
;
.examine0
code -
 message cr
code +
 IF NOUN1<MAXOBJECTPLUS1 THEN EXAMINE1
 M1=2112 ; can't tell you any more
 gosub @printM1
 goto @examret
;
.EXAMINE1
 GOSUB @SPECIALPREEXAMINE
 IF RESULT=TRUE THEN EXAMRET ; something prevents main examine message
 verb=iam ; e.g. 'the knife is..' or 'you are..'
 gosub @printOBJECTverb
 M1=EXAMINEMESSAGES
 ADD M1,OBJECT
 gosub @printM1dot
 processed=false
 GOSUB @SPECIALEXAMINE
 if processed=true then examret
 SEARCHPOS=OBJECT
 HISEARCHPOS=NONSPECIFIC
 GOSUB @PRINTOBJECTS
.examret
code -
 return
;---
.ring
code +
;
;=====
 if object<>doorbell then ringret
 gosub @PrintActorActionDot
 if room=currentuserroom then ringbell1
code -
 message cr
 message 2800 ; omni message for doorbell ringing
code +
.ringbell1
 gosub @AAreachout
;
; does player ring bell voluntarily?
 if actor<>user then usernotring
 m1=2827 ; a voice shouted, "come in"
 gosub @printm1dot
 goto ringret
.usernotring
;
 FrontDoorOpened=false ; new arrivals wait for front door to be opened
 object=jarvis
 x6=110
 add x6,actor
 gosub @newracetrackforobject ; send jarvis to answer the door
;=====
;
.ringret
code -
 return
;
;=====
; Answer telephone...
.Answer
code +
 if object<>telephone then answerret
 gosub @printactoraction
 m1=2530
 gosub @printm1dot ; ...and listened
 gosub @StartPickUpPhone
.answerret
.dialret
code -
 return
;---
; Dial telephone...
.Dial
code +
 if object<>telephone then dialret
 gosub @printactoractiondot
 gosub @StartPickUpPhone
;
; does player dial voluntarily?
 if actor<>user then usernotdial
 if executingracetrack<>false then usernotdial
 m1=2828 ; Sam breathed heavily and put the phone down.
 gosub @printm1dot
.usernotdial
;
code -
 return
;---
code +
.StartPickUpPhone
 sFrames=3
 ObjectNumber=PickUpPhone
 x1=1 ; facing north
 gosub @AAAnimateGotDir
.SPUPRet
 return
code -
;=====
;
;---
.sit
 if room<>currentuserroom then sitret
 message cr
code +
 gosub @printactorverb
 gosub @printdot
 x1=Object
 add x1,x1
 add x1,x1
 add x1,x1
 add x1,x1
 add x1,x1
 add x1,x1
 x2=14
 add x1,x2
 &x1=Hires(x1) ; get direction to face
 sFrames=3
 ObjectNumber=SitAnimation
 gosub @AAAnimateGotDir
code -
.sitret
 return
;---
.open
code +
 gosub @IsObjectOpen
 if result=true then openret ; already open
 gosub @SetOpenFlags
 gosub ShowOpenStatus ; open the object
.openret
code -
 return
;---
.close
code +
 gosub @IsObjectOpen
 if result=false then closeret ; already closed
 gosub @ClearOpenFlags
 gosub ShowOpenStatus ; close the object
.closeret
code -
 return
;---
; Display 'open' panel in front of OBJECT if required
; Set VERB=0 if no animation & messages are to be used
code +
.ShowOpenStatus
 noun1=object ; noun1 is not set up when called from displayallobjects
 if room<>currentuserroom then @OpenLogic
 v1=Object
 gosub @SetV1ACB
push v1
 if verb=0 then NoOpenCloseAni
 x1=14
 add v1,x1
 &x1=Hires(v1) ; get direction in which to face
 sFrames=3
 ObjectNumber=ReachLeftanimation
 gosub @AAAnimateGotDir
.NoOpenCloseAni
pop x1
;
; show open panel/closed panel
 &dv1=Hires(x1) ; get raster number
 add x1,c2
 &dv2=Hires(x1) ; x
 add x1,c2
 &dv3=Hires(x1) ; z
 add dv3,c1
 add x1,c2
 &dv4=Hires(x1) ; h
 add dv4,c1
 &x1=list4(42) ; list of raster number/ani sequence
.SearchOpenAni
 &x2=list4(x1) ; get raster to test
 if x2=0 then @NoOpenAni
 add x1,c2
 &x3=list4(x1) ; get ani sequence to use
 add x1,c2
 if x2<>dv1 then SearchOpenAni ; rasters don't match
;
; found an ani sequence to use...
 dv1=x3
 gosub @IsObjectOpen
 dv5=dInsertRedraw
 if result=true then ShowOpenPanel
 if verb=0 then NoOpenAni
 dv5=65535 ; remove from structure
.ShowOpenPanel
 dv6=0 ; non-reversed
push RasterOffset
 RasterOffset=0
 &WordWS(WordRasterOffset)=RasterOffset
 gosub @MCDrawObjectdv1 ; show new grafix
pop RasterOffset
.NoOpenAni
;
.OpenLogic
; show contents of wardrobe/chest or whatever
 if object<MinRoomObject then @OpenNotRoomObject
 if object>MaxRoomObject then @OpenNotRoomObject
;
 if verb=0 then NoOpenCloseMess
 gosub @printactoraction ; actor opened the wardrobe
 if verb<>iopen then NoOpenCloseMess
 m1=2830
 gosub @printm1 ; and found
.NoOpenCloseMess
push object
 &x1=list4(44) ; special objects table
 x2=40
 add x1,x2 ; Start at MinAllObject (object 20)
 object=MinAllObject
 totalobjectsprinted=0
.GetSpecialObjectPos
 x2=list4(x1) ; container type
 add x1,c1
 x3=list4(x1) ; room of container
 add x1,c1
 if x2<>noun1 then @NoSpecialObject
 if x3<>room then @NoSpecialObject
;
; OBJECT is contained within room object NOUN1
 hicurrentpos(object)=c0
 currentpos(object)=c0
 x1=Noun1
 gosub @IsObjectx1Open
 if result=false then @ObjectIsEnclosed
 currentpos(object)=room
.ObjectIsEnclosed
;
; set hires co-ords for the object
push x1
 if room=currentuserroom then ShowContainment
; Containment not in user room, and we don't yet know the pos 
; of the wardrobe, so place containments at the npc's pos
 dv4=PeopleHeight
 gosub @SetObjectToPersonPos ; drop at person floor pos + height dv4
 goto @objectisinroom
;
; Containment is in user room, so display at the containment pos 
; given to us by the container
.ShowContainment
 v1=Object
 gosub @SetV1ACB
 &ObjectNumber=Hires(v1)
 gosub @FindAndDecode ; get ysize of containment
 add ysize,ysize
 add ysize,ysize
 add ysize,ysize
 add ysize,ysize ; convert to pixels
 v2=v1
 add v2,c2 ; v2=coords for CONTAINMENT
 v3=v1
 add v3,c8 ; v3=access coords for CONTAINMENT
 v1=Noun1
 gosub @SetV1ACB
 add v1,c16 ; v1=containment coords for CONTAINER
 &dv2=Hires(v1) ; x
 &Hires(v2)=dv2
 &Hires(v3)=dv2
 add v1,c2
 add v2,c2
 add v3,c2
 &dv3=Hires(v1) ; z
 &Hires(v2)=dv3
 &Hires(v3)=dv3
 add v1,c2
 add v2,c2
 add v3,c2
 &dv4=Hires(v1) ; h
; containments are placed at the base of the container, 
; so we must add the containment's height
 add dv4,ysize
 &Hires(v2)=dv4
 &Hires(v3)=dv4
;
; Only certain containers have their contents visible...
 x1=noun1
 gosub @IsContainerx1Concealed
 if result=true then objectisvisible
 gosub @IsObjectx1Open
 x5=dInsertRedraw
 if result=true then ShowOpenContents
 if verb=0 then objectisvisible
 x5=65535 ; remove from structure
.ShowOpenContents
 gosub @DisplayObjectx5
.objectisvisible
 if verb<>iopen then objectisinroom
 m1=space
 gosub @printm1
 x1=object
 gosub @printanobjectx1
 add totalobjectsprinted,c1
.objectisinroom
pop x1
;
.NoSpecialObject
 add object,c1
 if object<MinRoomObject then @getSpecialObjectPos
 if verb<>iopen then DoneContentsList
 if totalobjectsprinted<>0 then DoneContentsList
 m1=2831 ; nothing (empty)
 gosub @printm1
.DoneContentsList
 if verb=0 then DCL1
 gosub @printdot
.DCL1
 gosub @AABuildViewMap
pop object
;
.OpenNotRoomObject
.PutNotRoomObject
 return
;---
; PUT, NOUN1=container, PREP, NOUN2=containment
; (the reversed noun order is used so that the container is 
; treated as the goal-directed object)
code -
.put
code +
push noun1
 noun1=noun2 ; swap noun1/2
pop noun2
 if noun2<MinRoomObject then PutNotRoomObject
 if noun2>MaxRoomObject then PutNotRoomObject
; NOUN2 is a ROOM OBJECT
 gosub @printactoractiondot
 gosub @AAreachout
 object=noun2
 gosub @SetOpenFlags ; make sure the container is open
 x2=noun1
 add x2,x2
 &x1=list4(44) ; special objects table
 add x1,x2
 list4(x1)=noun2 ; set container type
 add x1,c1
 list4(x1)=room ; set room of container
 verb=0 ; don't print any messages
 gosub @ShowOpenStatus
code -
 return
;---
; OPEN/CLOSED flags are used to DISABLE the OPEN 
; option in the menu
code +
.SetOpenFlags
 gosub @GetOpenBitx3
 or x3,x1 ; set the OPEN bit
 List4(x2)=x3 ; put it back
 return
;---
.ClearOpenFlags
 gosub @GetOpenBitx3
 x4=255
 xor x1,x4 ; negate the open bit to create a mask
 and x3,x1 ; clear the OPEN bit
 List4(x2)=x3 ; put it back
 return
;---
.IsObjectx1Open
push object
 object=x1
 gosub IsObjectOpen
pop object
 return
;---
.IsObjectOpen
 gosub @GetOpenBitx3
 and x3,x1 ; get the OPEN bit
 result=false
 if x3=0 then IOORet
 result=true
.IOORet
 return
;---
; Set up: x1 = OPEN bit for this object
;	  x2 = pointer to OPEN flags
;	  x3 = OPEN flags byte
.GetOpenBitx3
;
;=====
 x1=1 ; bit to OR
 if object=wardrobe then GetOpenByte
 x1=2 ; bit to OR
 if object=chest then GetOpenByte
 x1=4 ; bit to OR
 if object=fridge then GetOpenByte
;=====
;
 x1=8 ; bit to OR
.GetOpenByte
 &x2=List4(46)
 add x2,room
 x3=List4(x2) ; get OPEN flags for this room
 return
;---
; Are contents shown when container x1 is open
.IsContainerx1Concealed
;
;=====
 result=false
 if x1=wardrobe then ICX1CRet ; wardrobe not concealed
 if x1=Ntable then ICX1CRet
 if x1=bed then ICX1CRet
 if x1=chair then ICX1CRet
 if x1=sofa then ICX1CRet
;=====
;
 result=true
.ICX1CRet
 return
;---
.MoveObject
 currentpos(Object)=pos
 hicurrentpos(Object)=hipos
 if object<MinAllObject then MORet
 if object>MaxAllObject then MORet
 &x1=list4(44) ; special objects table
 x2=object
 add x2,x2
 add x1,x2 ; special position when contained in raster objects
 &List4(x1)=c0 ; clear the position
.MORet
 return
;---
.gdwaitforperson
; noun1 is person to wait for
; this command is always executed off the command queue
 verb=0 ; fool specialcheckifpresent
 object=noun1
 gosub @checkifpresent
 if result=true then @gdwaitend ; it's arrived
 return
;---
.gdwaitforpersontoleave
; noun1 is person to wait until he leaves
; this command is always executed off the command queue
 verb=0 ; fool specialcheckifpresent
 object=noun1
 gosub @checkifpresent
 if result=false then @gdwaitend ; he's gone
 return
;---
.gdwaitforperiod
; noun1:noun2 is period to wait for
; this command is always executed off the command queue
 value=noun1
 gosub @valuetimes256
 add value,noun2 ; noun1:noun2 word value
 if value=0 then @intelligentpop ; zero duration - time up
 sub value,c4 ;;c1 ; decrement
 if value>negative then @gdwaitend ; timer run out - time up
 gosub @npcgetcurrent
 add x1,c3 ; point x1 to noun1
 noun1=value
 asr noun1
 asr noun1
 asr noun1
 asr noun1
 asr noun1
 asr noun1
 asr noun1
 asr noun1
 noun2=255
 and noun2,value
 npcstack(x1)=noun1 ; poke back the decremented value
 add x1,c1 ; point x1 to noun2
 npcstack(x1)=noun2
 return
;---
.gdwaitend
 executeprocessed=false ; nothing useful done
 goto @intelligentpop
;---
.SHORTWAIT
; wait for a single turn
 executeprocessed=true ; make it take time
 return
;---
